define [
  'validate'
], ->

  'use strict'

  ###
  Extendendo o prototype do $.validator
  ###
  $.extend $.validator::,

    ###
    Retorna o elemento para exibição do sumário de erro presente no formulário
    @return {$} jQuery object com o elemento presente no formulário.
    ###
    getErrorSummary: ->
      $(@currentForm).find '.error-summary'

  $.extend $.validator.messages,
    required       : 'Campo obrigat&oacute;rio'
    remote         : 'Por favor, corrija este campo'
    email          : 'Forne&ccedil;a um email v&aacute;lido'
    url            : 'Forne&ccedil;a uma URL v&aacute;lida'
    date           : 'Forne&ccedil;a uma data v&aacute;lida'
    dateISO        : 'Forne&ccedil;a uma data v&aacute;lida (ISO)'
    dateITA        : 'Forne&ccedil;a uma data v&aacute;lida'
    number         : 'Forne&ccedil;a um n&uacute;mero v&aacute;lido'
    digits         : 'Forne&ccedil;a somente d&iacute;gitos'
    creditcard     : 'Forne&ccedil;a um cart&atilde;o de cr&eacute;dito v&aacute;lido'
    equalTo        : 'Forne&ccedil;a o mesmo valor que o campo anterior.'
    accept         : 'Forne&ccedil;a um valor com uma extens&atilde;o v&aacute;lida'
    alphanumeric   : 'Forne&ccedil;a apenas letras ou números'
    maxlength      : $.validator.format 'Forne&ccedil;a n&atilde;o mais que {0} caracteres'
    minlength      : $.validator.format 'Forne&ccedil;a ao menos {0} caracteres'
    minWords       : $.validator.format 'Forne&ccedil;a ao menos {0} palavras'
    rangelength    : $.validator.format 'Forne&ccedil;a um valor entre {0} e {1} caracteres de comprimento'
    range          : $.validator.format 'Forne&ccedil;a um valor entre {0} e {1}'
    max            : $.validator.format 'Forne&ccedil;a um valor menor ou igual a {0}'
    min            : $.validator.format 'Forne&ccedil;a um valor maior ou igual a {0}'
    summary        : $.validator.format 'Seu formulário contém {0} {1}, verifique os detalhes acima'
    error_singular : 'erro'
    error_plural   : 'erros'

  $.validator.setDefaults
    validClass: 'has-success'
    errorClass: 'has-error'

    ###
    Método que faz a tratativa para exibição de erros no
    formulário sendo validado.

    @param  {[type]} errorMap  [description]
    @param  {[type]} errorList [description]
    @return {[type]}           [description]
    ###
    showErrors: (errorMap, errorList) ->
      # Executa a exibição de erros padrão
      @defaultShowErrors()

    ###
    Método que determina onde a mensagem de erro deve aparecer.

    @param  {[type]} error   [description]
    @param  {[type]} element [description]
    @return {[type]}         [description]
    ###
    errorPlacement: (error, element) ->
      error.addClass 'help-block'
      formGroup = element.closest('.form-group')
      if !formGroup.find('label.help-block.has-error, label.help-block.has-success').length
        error.appendTo element.closest('.form-group')


    ###
    Marca o campo com erro.

    @param  {[type]} element    [description]
    @param  {[type]} errorClass [description]
    @param  {[type]} validClass [description]
    @return {[type]}            [description]
    ###
    highlight: (element, errorClass, validClass) ->
      $(element).closest('.form-group').addClass(errorClass).removeClass validClass


    ###
    Limpa o campo com erro e marca o campo como validado.

    @param  {[type]} element    [description]
    @param  {[type]} errorClass [description]
    @param  {[type]} validClass [description]
    @return {[type]}            [description]
    ###
    unhighlight: (element, errorClass, validClass) ->
      $formGroup  = $(element).closest('.form-group')
      $errorLabel = $formGroup.find('.help-block.has-error')

      if !$errorLabel.length or $errorLabel.is ':hidden'
        $formGroup.removeClass(errorClass).addClass validClass

  ###
  [setValidationRules description]
  ###
  $.fn.extend setValidationRules: (rules) -> $(this).data 'validation-rules', rules

  $.validator.addMethod('letras_e_numeros', (value) =>
    patt = new RegExp("^(?=.*[a-zA-Z])(?=.*[0-9])")
    return patt.test(value)

  , 'Necessário conter letras e números.')

  $.validator.addMethod('cep', (value) =>

    objER = new RegExp("^[0-9]{2}[0-9]{3}-[0-9]{3}")

    value = value.replace(/^s+|s+$/g, '')
    if(value.length > 0)
      if(objER.test(value))
        return true
      else
        return false
    else
      return blnVazio

   , 'CEP Inválido.')

   $.validator.addMethod('cpf', (cpf) =>
    cpf = cpf.replace(/\./g, '')
    cpf = cpf.replace '-', ''
    return false  if cpf.length isnt 11 or cpf is "00000000000" or cpf is "11111111111" or cpf is "22222222222" or cpf is "33333333333" or cpf is "44444444444" or cpf is "55555555555" or cpf is "66666666666" or cpf is "77777777777" or cpf is "88888888888" or cpf is "99999999999"
    add = 0
    i = 0
    while i < 9
      add += parseInt(cpf.charAt(i)) * (10 - i)
      i++
    rev = 11 - (add % 11)
    rev = 0  if rev is 10 or rev is 11
    return false  unless rev is parseInt(cpf.charAt(9))
    add = 0
    i = 0
    while i < 10
      add += parseInt(cpf.charAt(i)) * (11 - i)
      i++
    rev = 11 - (add % 11)
    rev = 0  if rev is 10 or rev is 11
    return false  unless rev is parseInt(cpf.charAt(10))
    true
   , 'CPF Inválido')

   $.validator.addMethod('cnpj', (cnpj) =>
    cnpj = cnpj.replace(/[^\d]+/g, "")
    return false  if cnpj is ""
    return false  unless cnpj.length is 14

    # Elimina CNPJs invalidos conhecidos
    return false  if cnpj is "00000000000000" or cnpj is "11111111111111" or cnpj is "22222222222222" or cnpj is "33333333333333" or cnpj is "44444444444444" or cnpj is "55555555555555" or cnpj is "66666666666666" or cnpj is "77777777777777" or cnpj is "88888888888888" or cnpj is "99999999999999"

    # Valida DVs
    tamanho = cnpj.length - 2
    numeros = cnpj.substring(0, tamanho)
    digitos = cnpj.substring(tamanho)
    soma = 0
    pos = tamanho - 7
    i = tamanho
    while i >= 1
      soma += numeros.charAt(tamanho - i) * pos--
      pos = 9  if pos < 2
      i--
    resultado = (if soma % 11 < 2 then 0 else 11 - soma % 11)
    return false  unless resultado is parseInt(digitos.charAt(0))
    tamanho = tamanho + 1
    numeros = cnpj.substring(0, tamanho)
    soma = 0
    pos = tamanho - 7
    i = tamanho
    while i >= 1
      soma += numeros.charAt(tamanho - i) * pos--
      pos = 9  if pos < 2
      i--
    resultado = (if soma % 11 < 2 then 0 else 11 - soma % 11)
    return false  unless resultado is parseInt(digitos.charAt(1))
    true
   , 'CNPJ Inválido')
